package com.zshy.base.kit.http;

import com.alibaba.fastjson2.JSONObject;
import com.zshy.base.core.contract.enums.ResultCodeEnum;
import com.zshy.base.core.contract.exception.HttpClientException;
import com.zshy.base.core.utils.BizAssert;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import java.io.IOException;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * Http 工具类
 *
 * @author xtp
 * @date 2023/11/27
 */
public class HttpKit {

    private HttpKit() {
    }

    /**
     * 带参数的get请求
     *
     * @param url   请求地址，不能为空或空白字符串
     * @param param 请求参数，可以为null
     * @return 返回请求响应的字符串结果
     * @throws HttpClientException 当执行请求时发生异常时抛出
     */
    public static String doGet(String url, Map<String, String> param) {
        // 创建Httpclient对象
        BizAssert.assertTrueWarn(StringUtils.isBlank(url), ResultCodeEnum.URL_IS_NULL);
        try (CloseableHttpClient httpclient = HttpClients.createDefault()) {

            // 创建uri
            URIBuilder builder = new URIBuilder(url);
            if (param != null) {
                for (Map.Entry<String, String> entry : param.entrySet()) {
                    builder.addParameter(entry.getKey(), entry.getValue());
                }
            }
            URI uri = builder.build();
            // 创建http GET请求并执行
            try (CloseableHttpResponse httpResponse = httpclient.execute(new HttpGet(uri))) {
                // 判断返回状态是否为200
                if (httpResponse.getStatusLine().getStatusCode() == 200) {
                    return EntityUtils.toString(httpResponse.getEntity(), StandardCharsets.UTF_8);
                }
                return null;
            } catch (Exception e) {
                throw new HttpClientException(e);
            }
        } catch (Exception e) {
            throw new HttpClientException(e);
        }
    }

    /**
     * 不带参数的get请求
     *
     * @param url 请求地址，不能为null或空字符串
     * @return 返回请求响应的字符串结果
     * @throws HttpClientException 当执行请求时发生异常时抛出
     */
    public static String doGet(String url) {
        return doGet(url, null);
    }


    /**
     * 带有header参数的GET请求
     *
     * @param url     请求地址，不能为null或空字符串
     * @param headers 请求头参数，可以为null
     * @return 返回请求结果的字符串，如果请求失败则返回空字符串
     * @throws HttpClientException 当执行请求时发生异常时抛出
     */
    public static String doGetByHeaders(String url, Map<String, String> headers) {
        // 创建Httpclient对象
        if (url == null || url.isEmpty()) {
            throw new IllegalArgumentException("URL cannot be null or empty.");
        }
        try (CloseableHttpClient httpclient = HttpClients.createDefault()) {
            // 创建uri
            URIBuilder builder = new URIBuilder(url);
            URI uri = builder.build();
            // 创建http GET请求
            HttpGet httpGet = new HttpGet(uri);
            if (headers != null) {
                for (Map.Entry<String, String> entry : headers.entrySet()) {
                    httpGet.addHeader(entry.getKey(), entry.getValue());
                }
            }
            try (CloseableHttpResponse response = httpclient.execute(httpGet)) {
                if (response.getStatusLine().getStatusCode() == 200) {
                    return EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
                }
                return null;
            } catch (Exception e) {
                throw new HttpClientException(e);
            }
        } catch (Exception e) {
            throw new HttpClientException(e);
        }
    }

    /**
     * 带有Org-Key请求头参数的GET请求
     *
     * @param url    请求地址，不能为空或空白字符串
     * @param orgKey Org-Key请求头参数
     * @return String 请求结果的字符串形式，如果请求失败或状态码不是200则返回空字符串
     * @throws HttpClientException 当执行请求时发生异常时抛出
     */
    public static String doGetByHeader(String url, String orgKey) {
        // 创建Httpclient对象
        BizAssert.assertTrueWarn(StringUtils.isBlank(url), ResultCodeEnum.URL_IS_NULL);
        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            // 创建uri
            URIBuilder builder = new URIBuilder(url);
            URI uri = builder.build();
            // 创建http GET请求
            HttpGet httpGet = new HttpGet(uri);
            httpGet.addHeader("Org-Key", orgKey);
            // 执行请求
            try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
                // 判断返回状态是否为200
                if (response.getStatusLine().getStatusCode() == 200) {
                    return EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
                }
                return null;
            } catch (IOException e) {
                throw new HttpClientException(e);
            }
        } catch (Exception e) {
            throw new HttpClientException(e);
        }
    }

    /**
     * 执行带参数的POST请求，并返回请求结果。
     *
     * @param url   请求地址，不能为空。
     * @param param 请求参数，可以为空。
     * @return 返回请求结果的字符串形式，如果请求失败或状态码不是200则返回空字符串。
     * @throws HttpClientException 当执行请求时发生异常时抛出。
     */
    public static String doPost(String url, Map<String, String> param) {
        // 验证URL是否为空
        BizAssert.assertTrueWarn(StringUtils.isBlank(url), ResultCodeEnum.URL_IS_NULL);
        // 创建Httpclient对象
        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            // 创建Http Post请求
            HttpPost httpPost = new HttpPost(url);
            httpPost.addHeader("Content-Type", "application/json; charset=utf-8");
            // 如果请求参数不为空
            // 创建参数列表
            if (!param.isEmpty()) {
                List<NameValuePair> paramList = new ArrayList<>();
                for (Map.Entry<String, String> entry : param.entrySet()) {
                    String key = entry.getKey();
                    String value = entry.getValue();
                    paramList.add(new BasicNameValuePair(key, value));
                }
                // 构造UrlEncodedFormEntity对象，模拟表单提交
                // 模拟表单
                UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList);
                httpPost.setEntity(entity);
            }
            // 执行请求
            try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
                // 判断返回状态是否为200
                if (response.getStatusLine().getStatusCode() == 200) {
                    // 返回请求结果的字符串形式
                    return EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
                }
                // 如果状态码不是200，返回空字符串
                return null;
            } catch (IOException e) {
                // 如果执行请求时发生IO异常，抛出HttpClientException异常
                throw new HttpClientException(e);
            }
        } catch (Exception e) {
            // 如果执行请求时发生IO异常，抛出HttpClientException异常
            throw new HttpClientException(e);
        }
    }


    /**
     * 发送带参数的POST请求，并返回请求结果。
     *
     * @param url     请求地址，不能为null或空字符串。
     * @param param   请求参数，可以为null或空Map。
     * @param headers 请求头信息，可以为null或空Map。
     * @return 请求结果的字符串形式，如果请求失败或状态码不是200则返回空字符串。
     * @throws HttpClientException 当执行请求时发生异常时抛出。
     */
    public static String doPostByHeader(String url, Map<String, Object> param, Map<String, String> headers) {
        // 验证URL是否为空
        BizAssert.assertTrueWarn(StringUtils.isBlank(url), ResultCodeEnum.URL_IS_NULL);
        String resultString = "";
        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            // 创建Http Post请求
            HttpPost httpPost = new HttpPost(url);
            httpPost.addHeader("Content-Type", "application/json; charset=utf-8");
            // 创建参数列表
            if (param != null && !param.isEmpty()) {
                // 模拟表单
                StringEntity entity = new StringEntity(JSONObject.toJSONString(param));
                httpPost.setEntity(entity);
            }
            // 添加请求头
            if (!headers.isEmpty()) {
                for (Map.Entry<String, String> entry : headers.entrySet()) {
                    httpPost.addHeader(entry.getKey(), entry.getValue());
                }
            }
            // 执行http请求
            try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
                return EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
            } catch (Exception e) {
                throw new HttpClientException(e);
            }
        } catch (Exception e) {
            throw new HttpClientException(e);
        }
    }

    /**
     * 发送带参数的POST请求，并返回请求结果。
     *
     * @param url        请求地址
     * @param jsonObject 请求参数，需要是JSONObject类型
     * @return 请求结果的字符串形式，如果请求失败或状态码不是200则返回空字符串
     * @throws HttpClientException 当执行请求时发生异常时抛出
     */
    public static String doPost(String url, JSONObject jsonObject) {
        // 创建Httpclient对象
        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            // 创建Http Post请求
            HttpPost httpPost = new HttpPost(url);
            httpPost.addHeader("Content-Type", "application/json; charset=utf-8");
            // 创建请求内容
            StringEntity entity = new StringEntity(jsonObject.toString(), ContentType.APPLICATION_JSON);
            httpPost.setEntity(entity);
            // 执行http请求并处理响应
            try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
                if (response.getStatusLine().getStatusCode() == 200) {
                    return EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
                }
                // 状态码不是200时返回空字符串
                return null;
            } catch (IOException e) {
                throw new HttpClientException(e);
            }
        } catch (IOException e) {
            throw new HttpClientException(e);
        }
    }

    /**
     * 不带参数的POST请求
     *
     * @param url 请求地址
     * @return 请求结果的字符串形式
     * @throws HttpClientException 当执行请求时发生异常时抛出
     */
    public static String doPost(String url) {
        return doPost(url, Collections.emptyMap());
    }

    /**
     * 发送JSON格式的POST请求
     *
     * @param url       请求地址
     * @param json      请求参数，以JSON格式字符串表示
     * @param tokenName 验证Token的名称
     * @param token     验证Token的值
     * @return 请求结果的字符串形式
     * @throws HttpClientException 当执行请求时发生异常时抛出
     */
    public static String doPostJson(String url, String json, String tokenName, String token) {
        // 创建Httpclient对象
        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            // 创建Http Post请求
            HttpPost httpPost = new HttpPost(url);
            httpPost.addHeader("Content-Type", "application/json; charset=utf-8");
            httpPost.addHeader(tokenName, token);
            // 创建请求内容
            StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON);
            httpPost.setEntity(entity);
            // 执行http请求并处理响应
            try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
                if (response.getStatusLine().getStatusCode() == 200) {
                    return EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
                }
                // 状态码不是200时返回空字符串
                return null;
            } catch (IOException e) {
                throw new HttpClientException(e);
            }
        } catch (IOException e) {
            throw new HttpClientException(e);
        }
    }

    /**
     * 发送JSON格式的POST请求
     *
     * @param url       请求地址
     * @param json      请求参数，以JSON格式字符串表示
     * @param headerMap 请求头信息，包含key-value键值对
     * @return 请求结果的字符串形式
     * @throws HttpClientException 当执行请求时发生异常时抛出
     */
    public static String doPostJson(String url, String json, Map<String, String> headerMap) {
        // 创建Httpclient对象
        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            // 创建Http Post请求
            HttpPost httpPost = new HttpPost(url);
            httpPost.addHeader("Content-Type", "application/json; charset=utf-8");
            if (!headerMap.isEmpty()) {
                for (Map.Entry<String, String> entry : headerMap.entrySet()) {
                    httpPost.addHeader(entry.getKey(), entry.getValue());
                }
            }
            // 创建请求内容
            StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON);
            httpPost.setEntity(entity);
            // 执行http请求并处理响应
            try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
                if (response.getStatusLine().getStatusCode() == 200) {
                    return EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
                }
                // 状态码不是200时返回空字符串
                return null;
            } catch (IOException e) {
                throw new HttpClientException(e);
            }
        } catch (IOException e) {
            throw new HttpClientException(e);
        }
    }
}
